﻿/*======================================================================
== Copyright : BlueCurve (c)
== Licence   : Gnu/GPL v2.x
== Author    : Teddy Albina
== Email     : bluecurveteam@gmail.com
== Web site  : http://www.codeplex.com/BlueCurve
========================================================================*/
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Threading;
using BlueCurve.IRemoteOperations;

namespace QueryServer
{
    /// <summary>
    /// Service wcf
    /// </summary>
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode=InstanceContextMode.PerSession)]
    public class Tcpservice : IRemoteIndexation
    {
        #region 'Configuration'

        /// <summary>
        /// Permets de savoir si le serveur est en mode de sauvegarde
        /// </summary>
        private bool m_IsBackup = false;
        /// <summary>
        /// Permets de savoir si des recherches peuvent être éffectuer
        /// </summary>
        private bool m_IsSearchable = true;
        /// <summary>
        /// Objet pour la synchronisation
        /// </summary>
        private ReaderWriterLockSlim m_ThreadsLock = new ReaderWriterLockSlim();
        /// <summary>
        /// Evenement d'arret de l'application
        /// </summary>
        public static event EventHandler _StopApplication;
        /// <summary>
        /// Evenement de redemarrae de l'application
        /// </summary>
        public static event EventHandler _RestartApplication;
        /// <summary>
        /// Passe le serveur en mode backup
        /// </summary>
        public static event EventHandler EnterBackupMode;
        
        /// <summary>
        /// Constructeur
        /// </summary>
        public Tcpservice()
        {
            LuceneIndexWriter.EndOfBackupMode += new EventHandler(LuceneIndexWriter_EndOfBackupMode);
        }

        #endregion





        #region IRemoteSearch Membres
      
        /// <summary>
        /// Fonctions servant à effectuer des recherches
        /// </summary>
        /// <param name="querystring">Requete envoyé par l'utilisateur</param>
        /// <returns><![CDATA[List<BlueCurve.SearchContract.SearchData>]]></returns>
        [OperationBehavior]
        public List<BlueCurve.SearchContract.SearchData> Search(BlueCurve.SearchContract.SearchQuery Querydata)
        {
            try
            {
                m_ThreadsLock.EnterReadLock();
                try {
                    if (this.m_IsBackup || !this.m_IsSearchable)
                        return null;
                } finally {
                    m_ThreadsLock.ExitReadLock();
                }

                LuceneIndexReader searcher = new LuceneIndexReader("Index");
                return searcher.Search(Querydata);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Fonctions servant à effectuer des recherches
        /// </summary>
        /// <param name="querystring">Requete envoyé par l'utilisateur</param>
        /// <returns>string</returns>
        [OperationBehavior]
        public virtual string Search(BlueCurve.SearchContract.SearchQuery Querydata, bool e)
        {
            try
            {
                m_ThreadsLock.EnterReadLock();
                try {
                    if (this.m_IsBackup || !this.m_IsSearchable)
                        return null;
                } finally {
                    m_ThreadsLock.ExitReadLock();
                }

                LuceneIndexReader searcher = new LuceneIndexReader("Index");
                return searcher.Search(Querydata, true);
            }
            catch
            {
                return null;
            }
        }
        
        /// <summary>
        /// Permet de redémarrer l'application
        /// </summary>
        [OperationBehavior]
        public void RestartApplication()
        {
            this.m_IsSearchable = false;
            BlueCurve.MemoryCache.StopCache.Raise_StopCache();
            _RestartApplication("", EventArgs.Empty);
        }
        
        /// <summary>
        /// Permet d'arreter l'application
        /// </summary>
        [OperationBehavior]
        public void StopApplication()
        {
            this.m_IsSearchable = false;
            BlueCurve.MemoryCache.StopCache.Raise_StopCache();
            _StopApplication("", EventArgs.Empty);
        }

        /// <summary>
        /// Mets le serveur en mode de sauvegarde.
        /// Quand il est activé,une sauvegarde de la base de données est effectuer
        /// sur un bloc du système de fichier
        /// </summary>
        /// <returns>bool</returns>
        [OperationBehavior]
        public void BackupMode()
        {
            m_ThreadsLock.EnterWriteLock();
            try {
                this.m_IsBackup = true;
            } finally {
                m_ThreadsLock.ExitWriteLock();
            }

            EnterBackupMode("", EventArgs.Empty);
        }

        /// <summary>
        /// Permet d'obtenir le nombre de documents indexés
        /// </summary>
        /// <returns>ulong</returns>
        [OperationBehavior]
        public int IndexCount()
        {
            return LuceneIndexWriter.CountDocument();
        }

        /// <summary>
        /// Permet l'indexation d'un document
        /// </summary>
        /// <param name="data">Données à indexer</param>
        /// <returns>bool</returns>
        [OperationBehavior]
        public bool IndexOperation(BlueCurve.IndexationContract.IndexationData data)
        {
            m_ThreadsLock.EnterReadLock();
            try {
                if (this.m_IsBackup || !this.m_IsSearchable)
                    return false;
            } finally {
                m_ThreadsLock.ExitReadLock();
            }

            return LuceneIndexWriter.Add(data);
        }

        /// <summary>
        /// Retourne les méta données pour 
        /// la mise à jour du document
        /// </summary>
        /// <param name="path">Chemin d'accès du document</param>
        /// <returns>BlueCurve.SearchContract.UpdateMetaData</returns>
        [OperationBehavior]
        public BlueCurve.SearchContract.UpdateMetaData GetMetaDataForUpdate(string path)
        {
            try
            {
                m_ThreadsLock.EnterReadLock();
                try {
                    if (this.m_IsBackup || !this.m_IsSearchable)
                        return null;
                } finally {
                    m_ThreadsLock.ExitReadLock();
                }

                LuceneIndexReader searcher = new LuceneIndexReader("Index");
                return searcher.GetMetaDataForUpdate(path);
            }
            catch
            {
                return null;
            }
        }

        #endregion





        #region 'Event'

        /// <summary>
        /// Fonction attachée à la fin du mode de sauvegarde
        /// </summary>
        private void LuceneIndexWriter_EndOfBackupMode(object sender, EventArgs e)
        {
            m_ThreadsLock.EnterWriteLock();
            try
            {
                this.m_IsBackup = false;
                this.m_IsSearchable = true;
            }
            finally
            {
                m_ThreadsLock.ExitWriteLock();
            }
        }

        #endregion
    }
}
